﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.Entity;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

using BEX.WebUI.Entities;
using BEX.Core;
using BEX.Core.Exchange;
using BEX.Core.Exchange.MtGox;
using BEX.Core.Exchange.BITFINEX;
using BEX.Core.Exchange.BITSTAMP;
using BEX.Core.Exchange.BTCE;
using BEX.Core.Exchange.CAMPBX;
using BEX.Core.Exchange.Coinbase;

using BEX.RuleMonitor;

namespace BEX.WebUI.Models
{
    public class ArbitrageRuleModel : ArbitrageRule
    {
        private BTC_SMSEntities db = new BTC_SMSEntities();

        private ALERT_RULE_ARBITRAGE _source = null;

        public ALERT_RULE_ARBITRAGE Source
        {
            get { return _source; }
            set { _source = value; }
        }

        public SelectList Currencies
        {
            get
            {
                SelectList _list = GetSupportedCurrencies(ExchangeA, ExchangeB);

                return _list;
            }
        }

        public static SelectList GetSupportedCurrencies(ExchangeType a, ExchangeType b)
        {
            Exchange _a = GetInstance(a);
            Exchange _b = GetInstance(b);

            List<CurrencyPair> _union = _a.SupportedPairs.Intersect<CurrencyPair>(_b.SupportedPairs).ToList();

            SelectList _list;

            _list = new SelectList(_union, "Title", "Title");

            return _list;

        }

        public static Exchange GetInstance(ExchangeType t)
        {
            Exchange res = null;

            switch (t)
            {
                case (ExchangeType.BITFINEX):
                    res = new Bitfinex();
                    break;
                case (ExchangeType.BITSTAMP):
                    res = new Bitstamp();
                    break;
                case (ExchangeType.BTCE):
                    res = new BTCE();
                    break;
                case (ExchangeType.CAMPBX):
                    res = new CampBX();
                    break;
                case (ExchangeType.COINBASE):
                    res = new Coinbase();
                    break;
                case (ExchangeType.MTGOX):
                    res = new MtGox();
                    break;


            }

            return res;
        }


        [Required]
        [Display(Name = "Currency Pair")]
        new public string Pair
        {
            get { return base.Pair.ToString(); }
            set
            {

                string[] _split = value.Split('/');


                base._pair = new CurrencyPair();
                base._pair.Base = (CurrencyType)Enum.Parse(typeof(CurrencyType), _split[0], true);
                base._pair.Counter = (CurrencyType)Enum.Parse(typeof(CurrencyType), _split[1], true);

            }
        }

        [Required]
        [Display(Name = "Exchange B")]
        new public ExchangeType ExchangeB
        {
            get { return base.ExchangeB; }
            set { base.ExchangeB = value; }
        }

        [Required]
        [Display(Name = "Exchange A")]
        new public ExchangeType ExchangeA
        {
            get { return base.ExchangeA; }
            set { base.ExchangeA = value; }
        }

        [Required]
        [Display(Name = "Percent Difference")]
        new public decimal Percent
        {
            get { return base.Percent; }
            set { base.Percent = value; }
        }

        public ArbitrageRuleModel()
        {
            ExchangeA = ExchangeType.MTGOX;
            ExchangeB = ExchangeType.BITSTAMP;
            _pair = new CurrencyPair() { Base = CurrencyType.BTC, Counter = CurrencyType.USD };

        }

        public static List<ArbitrageRuleModel> GetAllForUser()
        {
            BTC_SMSEntities db = new BTC_SMSEntities();

            List<int> _r = (from ACCOUNT_RULE_ARBITRAGE in db.ACCOUNT_RULE_ARBITRAGE
                            where ACCOUNT_RULE_ARBITRAGE.ACCOUNT_ID == SourceUser.AccountId
                            select ACCOUNT_RULE_ARBITRAGE).Select(r => r.RULE_ID).ToList();


            List<ALERT_RULE_ARBITRAGE> _l = (from ALERT_RULE_ARBITRAGE in db.ALERT_RULE_ARBITRAGE
                                           where _r.Contains(ALERT_RULE_ARBITRAGE.ID)
                                           select ALERT_RULE_ARBITRAGE).ToList();


            /*            List<ALERT
            > _l = (from ALERT_RULE_ARBITRAGE in db.ALERT_RULE_ARBITRAGE
                                                           where _r.Contains(ALERT_RULE_ARBITRAGE.ID)
                                                         select ALERT_RULE_ARBITRAGE).Select(r =>
                            new ArbitrageRuleModel()
                            {
                                _id = r.ID,
                                _pair = new CurrencyPair() { Base = (CurrencyType)r.BASE_CURRENCY_ID, Counter = (CurrencyType)r.COUNTER_CURRENCY_ID },
                                Percent = r.PERCENTAGE,
                                ExchangeA = (ExchangeType)r.EXCHANGE_A,
                                ExchangeB = (ExchangeType)r.EXCHANGE_B,
                                _source = r
                            }).ToList();
                        */
            return _l.Select(r =>
                            new ArbitrageRuleModel()
                            {
                                _id = r.ID,
                                _pair = new CurrencyPair() { Base = (CurrencyType)r.BASE_CURRENCY_ID, Counter = (CurrencyType)r.COUNTER_CURRENCY_ID },
                                Percent = r.PERCENTAGE,
                                ExchangeA = (ExchangeType)r.EXCHANGE_A,
                                ExchangeB = (ExchangeType)r.EXCHANGE_B,
                                _source = r
                            }).ToList();
        }

        public static ArbitrageRuleModel GetByID(int id)
        {
            BTC_SMSEntities db = new BTC_SMSEntities();

            ALERT_RULE_ARBITRAGE alert_rule_arbitrage = db.ALERT_RULE_ARBITRAGE.Find(id);

            ArbitrageRuleModel res = new ArbitrageRuleModel();
            res._id = alert_rule_arbitrage.ID;
            res._pair = new CurrencyPair() { Base = (CurrencyType)alert_rule_arbitrage.BASE_CURRENCY_ID, Counter = (CurrencyType)alert_rule_arbitrage.COUNTER_CURRENCY_ID };
            res.Percent = alert_rule_arbitrage.PERCENTAGE;
            res.ExchangeA = (ExchangeType)alert_rule_arbitrage.EXCHANGE_A;
            res.ExchangeB = (ExchangeType)alert_rule_arbitrage.EXCHANGE_B;
            res._source = alert_rule_arbitrage;

            return res;
        }

        public void Save(bool insert)
        {
            UpdateSourceRow();


            if (insert)
                db.Entry(_source).State = EntityState.Added;
            else
                db.Entry(_source).State = EntityState.Modified;

            db.SaveChanges();
        }

        public static void Delete(int id)
        {
            BTC_SMSEntities db = new BTC_SMSEntities();

            ALERT_RULE_ARBITRAGE alert_rule_arbitrage = db.ALERT_RULE_ARBITRAGE.Find(id);
            db.ALERT_RULE_ARBITRAGE.Remove(alert_rule_arbitrage);
            db.SaveChanges();
        }

        private void UpdateSourceRow()
        {


            _source = db.ALERT_RULE_ARBITRAGE.Find(_id);

            if (_source == null)
                _source = new ALERT_RULE_ARBITRAGE();

            _source.PERCENTAGE = Percent;
            _source.BASE_CURRENCY_ID = (int)_pair.Base;
            _source.COUNTER_CURRENCY_ID = (int)_pair.Counter;
            _source.EXCHANGE_A = (int)ExchangeA;
            _source.EXCHANGE_B = (int)ExchangeB;



        }

    }

}